﻿using Common.Utility;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;

namespace Interface.Volcengine
{
    public class VolcengineSigner
    {
        private readonly string _accessKeyId = AppSetting.GetAppSetting("Volcengine:AccessKeyID");
        private readonly string _secretKey = AppSetting.GetAppSetting("Volcengine:SecretAccessKey");
        private readonly string _region;
        private readonly string _service;

        private static readonly JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore
        };

        public VolcengineSigner(string region = "cn-north-1", string service = "cv")
        {
            _region = region;
            _service = service;
        }

        public Dictionary<string, string> GenerateHeaders(string method, string url, object? requestBody)
        {
            var utcNow = DateTime.UtcNow;
            var dateStamp = utcNow.ToString("yyyyMMdd");
            var amzDate = utcNow.ToString("yyyyMMddTHHmmssZ");

            // 1. 规范请求（根据火山引擎API要求调整）
            var uri = new Uri(url);
            var requestBodyStr = "";
            if (requestBody != null)
            {
                requestBodyStr = JsonConvert.SerializeObject(requestBody, jsonSerializerSettings);
            }
            var hashedRequestPayload = ComputeSHA256(requestBodyStr);

            string signedHeaders = "host;x-date";
            StringBuilder canonicalHeaders = new StringBuilder();
            canonicalHeaders.Append($"host:{uri.Host}\n");
            if (!string.IsNullOrWhiteSpace(requestBodyStr))
            {
                signedHeaders = "host;x-content-sha256;x-date";
                canonicalHeaders.Append($"x-content-sha256:{hashedRequestPayload}\n");
            }
            canonicalHeaders.Append($"x-date:{amzDate}\n");

            var canonicalRequest = $"{method}\n{uri.AbsolutePath}\n{uri.Query.Substring(1)}\n{canonicalHeaders.ToString()}\n{signedHeaders}\n{hashedRequestPayload}";

            // 2. 生成待签名字符串
            var credentialScope = $"{dateStamp}/{_region}/{_service}/request";
            var hashedCanonicalRequest = ComputeSHA256(canonicalRequest);
            var stringToSign = $"HMAC-SHA256\n{amzDate}\n{credentialScope}\n{hashedCanonicalRequest}";

            // 3. 计算签名
            var signingKey = DeriveSigningKey(dateStamp);
            var signatureBytes = ComputeHMACSHA256(signingKey, stringToSign);
            var signature = ToHexString(signatureBytes);

            // 4. 构造 Authorization 头
            var authHeader = $"HMAC-SHA256 Credential={_accessKeyId}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}";

            var dic = new Dictionary<string, string>
            {
                { "Host", uri.Host },
                { "X-Date", amzDate },
                { "Authorization", authHeader },
                //{ "Content-Type", "application/json" } // 根据接口要求调整
            };
            if (!string.IsNullOrWhiteSpace(requestBodyStr))
            {
                dic.Add("X-Content-Sha256", hashedRequestPayload);
            }
            return dic;
        }

        private byte[] DeriveSigningKey(string dateStamp)
        {
            byte[] kSecret = Encoding.UTF8.GetBytes($"{_secretKey}");

            return ComputeHMACSHA256(
                    ComputeHMACSHA256(
                        ComputeHMACSHA256(
                                ComputeHMACSHA256(kSecret, dateStamp)
                            , _region)
                        , _service)
                , "request");
        }

        private string DeriveSigningKeyTest()
        {
            byte[] kSecret = Encoding.UTF8.GetBytes($"WkRZeE1EQmxPVGhsWWpWak5HVmtNbUUxTXpZeU9UVXlOMlE1TmpZeVlqTQ==");
            byte[] kDate = ComputeHMACSHA256(kSecret, "20240619");
            byte[] kRegion = ComputeHMACSHA256(kDate, "cn-beijing");
            byte[] kService = ComputeHMACSHA256(kRegion, "iam");
            byte[] k = ComputeHMACSHA256(kService, "request");
            return ToHexString(ComputeHMACSHA256(k, "HMAC-SHA256\n20240619T071306Z\n20240619/cn-beijing/iam/request\n5ed5bca3905e1fcbf789abb56a17c2d819674a3bcfa468ae476bd1ea80d135cb"));
        }

        private static byte[] ComputeHMACSHA256(byte[] key, string data)
        {
            using (var hmac = new HMACSHA256(key))
            {
                // 明确使用无 BOM 的 UTF-8 编码
                Encoding utf8NoBom = new UTF8Encoding(false);
                byte[] bytes = utf8NoBom.GetBytes(data);

                return hmac.ComputeHash(bytes);
            }
        }

        private static string ComputeSHA256(string input)
        {
            using (SHA256 sha256 = SHA256.Create())
            {
                // 明确使用无 BOM 的 UTF-8 编码
                Encoding utf8NoBom = new UTF8Encoding(false);
                byte[] bytes = utf8NoBom.GetBytes(input);

                byte[] hashBytes = sha256.ComputeHash(bytes);
                return ToHexString(hashBytes);
            }
        }

        private static string ToHexString(byte[] data)
        {
            return BitConverter.ToString(data).Replace("-", "").ToLowerInvariant();
        }
    }
}
